/*
 * @Author: qsy
 * @Date: 2024-07-23 14:44:15
 * @LastEditors: qsy
 * @LastEditTime: 2025-04-10 08:59:49
 * @Description: 请填写简介
 */
#include "my_mqtt.h"
#include "cJSON.h"
#include "my_uart.h"
#include "my_adc.h"

static const char *TAG = "MQTTS_EXAMPLE";

bool init_data_flag = false; // 初始化数据标志位




static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id); // 显示事件
    esp_mqtt_event_handle_t event = event_data; // 获取事件数据
    esp_mqtt_client_handle_t client = event->client; // 获取MQTT客户端句柄
    char topic[128];
    int msg_id;
    switch ((esp_mqtt_event_id_t)event_id) {
    case MQTT_EVENT_CONNECTED: // 连接成功
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");


        // 订阅主题
        // sprintf(topic, MQTT_SUB_TOPIC, DEVICE_ID);
        msg_id = esp_mqtt_client_subscribe(client, MQTT_SUB_TOPIC, 1);
        if(msg_id != -1){
            ESP_LOGI(TAG, "subscribe topic %s, msg_id=%d", topic, msg_id);
        }

        // 订阅事件主题 MQTT_EVENT_TOPIC_LEN
        msg_id = esp_mqtt_client_subscribe(client, MQTT_EVENT_TOPIC_LEN, 1);
        if(msg_id != -1){
            ESP_LOGI(TAG, "subscribe topic %s, msg_id=%d", topic, msg_id);
        }
        


        // 创建json数据
        cJSON *root = cJSON_CreateObject();
        cJSON_AddStringToObject(root, "id", "1744203496694");
        cJSON_AddStringToObject(root, "version", "1.0");    
        
        cJSON *params = cJSON_CreateObject();
        
        cJSON *air_humidity = cJSON_CreateObject();
        cJSON_AddNumberToObject(air_humidity, "value", 23);
        cJSON_AddItemToObject(params, "air_humidity", air_humidity);
        
        cJSON *air_temperature = cJSON_CreateObject();
        cJSON_AddNumberToObject(air_temperature, "value", 11);
        cJSON_AddItemToObject(params, "air_temperature", air_temperature);
        
        cJSON *light_intensity = cJSON_CreateObject();
        cJSON_AddNumberToObject(light_intensity, "value", 22);
        cJSON_AddItemToObject(params, "light_intensity", light_intensity);
        
        cJSON *soil_temp = cJSON_CreateObject();
        cJSON_AddNumberToObject(soil_temp, "value", 66); // 这里我将土壤温度改回了注释中的30
        cJSON_AddItemToObject(params, "soil_temp", soil_temp);
        
        cJSON_AddItemToObject(root, "params", params);


        // 转化json数据为字符串
        char *my_test_data = cJSON_Print(root);
        ESP_LOGI(TAG, "my_test_data=%s", my_test_data);


        int ret = esp_mqtt_client_publish(client, MQTT_PUB_TOPIC, my_test_data, strlen(my_test_data), 1, 0);
        if(ret != -1){
            // ESP_LOGI(TAG, "publish topic %s, msg_id=%d", MQTT_PUB_TOPIC, ret);
        }
        // 释放内存
        free(my_test_data);

        break;
    case MQTT_EVENT_DISCONNECTED: // 连接断开
        ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");

        break;

    case MQTT_EVENT_SUBSCRIBED: // 订阅成功
        ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED: // 取消订阅成功
        ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED");
        break;
    case MQTT_EVENT_PUBLISHED: // 发布成功
        // ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED");
        break;
    case MQTT_EVENT_DATA: // 收到消息
        // ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        // printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); // 这个是打印主题名字
        // printf("DATA=%.*s\r\n", event->data_len, event->data); // 这是打印收到的数据

        // 解析俩种json数据
        // {
        // "temp_max": 55,
        // "temp_min": 44
        // }
        // {
        // "time": "202501011200"
        // }
        // 解析json数据
        {
            // 把原始json数据转发至串口
            
            // // 计算需要发送的数据长度（包括终止符）
            // size_t data_len_with_terminator = event->data_len + 1;

            // // 创建一个新的缓冲区来存储数据和终止符
            // char data_with_terminator[data_len_with_terminator];

            // // 将原始数据复制到新的缓冲区
            // memcpy(data_with_terminator, event->data, event->data_len);

            // // 在新的缓冲区的末尾添加终止符
            // data_with_terminator[data_len_with_terminator - 1] = '\0';

            // // 发送数据（包含终止符）
            // uart_write_bytes(EX_UART_NUM, (const char*)data_with_terminator, data_len_with_terminator);


        }


        break;
    //-----------------------收到消息操作--------------------

    case MQTT_EVENT_ERROR: // 错误

        break;
    default:
        // ESP_LOGI(TAG, "Other event id:%d", event->event_id);
        // _ui_flag_modify(ui_wifi_warning, LV_OBJ_FLAG_HIDDEN, _UI_MODIFY_FLAG_REMOVE);
        break;
    }
}




esp_mqtt_client_handle_t client;
void mqtt_app_start(void)
{

    // 客户id
    char my_client_id[] = {"device"};

    // MQTT 服务器地址
    const esp_mqtt_client_config_t mqtt_cfg = {

        .uri = URL_TEST, // MQTT服务器地址
        .port = MQTT_PORT, // 端口
        .client_id = my_client_id, // 客户端ID

        // 设置遗嘱消息
        .lwt_qos = 1,                       // 遗嘱消息的 QoS
        .lwt_retain = 0,                    // 遗嘱消息是否需要保留
        // .disable_auto_reconnect = false,        // 禁用自动重连
        .out_buffer_size = 1024,            // 减小输出缓冲区大小
        .buffer_size = 1024,                // 减小输入缓冲区大小
        .task_stack = 1024*4,                 // 调整任务堆栈大小
        .network_timeout_ms = 3000,         // 网络超时时间
        // 用户名
        .username = MQTT_USER,
        .password = MQTT_PASS,
    };

    // 初始化MQTT客户端
    client = esp_mqtt_client_init(&mqtt_cfg);
    if (client == NULL) {
        ESP_LOGE(TAG, "Failed to initialize MQTT client");
        return;
    }

    // 注册事件处理函数
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);

    // 启动MQTT客户端
    esp_err_t err = esp_mqtt_client_start(client);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to start MQTT client: %d", err);
    }

}



/**
 * @description: 关闭mqtt
 * @return {*}
 */
void mqtt_app_stop(void){

    // 停止MQTT客户端
    esp_mqtt_client_stop(client);
    // 断开 MQTT 连接
    esp_mqtt_client_disconnect(client);
    // 销毁MQTT客户端
    esp_mqtt_client_destroy(client); 
}


/**
 * @description: 数据上传函数接口
 * @return {*}
 */

void mqtt_data_upload(my_value_t my_value){

    // 创建json数据
    cJSON *root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "id", "1744203496694");
    cJSON_AddStringToObject(root, "version", "1.0");    
    
    cJSON *params = cJSON_CreateObject();
    
    cJSON *air_humidity = cJSON_CreateObject();
    cJSON_AddNumberToObject(air_humidity, "value", my_value.air_humidity);
    cJSON_AddItemToObject(params, "air_humidity", air_humidity);
    
    cJSON *air_temperature = cJSON_CreateObject();
    cJSON_AddNumberToObject(air_temperature, "value", my_value.air_temperature);
    cJSON_AddItemToObject(params, "air_temperature", air_temperature);
    
    cJSON *light_intensity = cJSON_CreateObject();
    cJSON_AddNumberToObject(light_intensity, "value", my_value.light_intensity);
    cJSON_AddItemToObject(params, "light_intensity", light_intensity);
    
    cJSON *soil_temp = cJSON_CreateObject();
    cJSON_AddNumberToObject(soil_temp, "value", my_value.soil_humidity); // 这里我将土壤温度改回了注释中的30
    cJSON_AddItemToObject(params, "soil_temp", soil_temp);
    
    cJSON_AddItemToObject(root, "params", params);


    // 转化json数据为字符串
    char *my_test_data = cJSON_Print(root);
    // ESP_LOGI(TAG, "my_test_data=%s", my_test_data);


    int ret = esp_mqtt_client_publish(client, MQTT_PUB_TOPIC, my_test_data, strlen(my_test_data), 1, 0);
    if(ret != -1){
        // ESP_LOGI(TAG, "publish topic %s, msg_id=%d", MQTT_PUB_TOPIC, ret);
    }
    // 释放内存
    free(my_test_data);

}


/**
 * @description: 发送报警事件
 * @return {*}
 */
// {  
//   "id": "1744206837607",  
//   "version": "1.0",  
//   "params": {  
//     "warning_event": {  
//       "value": {  
//         "warn_para": 1  
//       }  
//     }  
//   }  
// }  
void mqtt_send_warning_event(uint8_t warn_para){
    // 创建json数据
    cJSON *root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "id", "1744206837607");
    cJSON_AddStringToObject(root, "version", "1.0");    
    
    cJSON *params = cJSON_CreateObject();
    
    cJSON *warning_event = cJSON_CreateObject();
    
    // 创建value对象并将warn_para添加到value对象中
    cJSON *value = cJSON_CreateObject();
    cJSON_AddNumberToObject(value, "warn_para", warn_para);
    
    cJSON_AddItemToObject(warning_event, "value", value);
    cJSON_AddItemToObject(params, "warning_event", warning_event);
    
    cJSON_AddItemToObject(root, "params", params);
    
    // 转化json数据为字符串
    char *my_test_data = cJSON_Print(root);
    // ESP_LOGI(TAG, "my_test_data=%s", my_test_data);

    // 发送事件的主题 $sys/3CqoyHWbCK/device/thing/event/post

    int ret = esp_mqtt_client_publish(client, MQTT_EVENT_TOPIC, my_test_data, strlen(my_test_data), 1, 0);
    if(ret != -1){
        // ESP_LOGI(TAG, "publish topic %s, msg_id=%d", MQTT_EVENT_TOPIC, ret); // 这里修改了MQTT_PUB_TOPIC为MQTT_EVENT_TOPIC以保持一致性
    }
    // 释放内存
    free(my_test_data);
    // 释放json对象
    cJSON_Delete(root);
}


/**
 * @description: 发送手动事件
 * @return {*}
 */
// {  
//   "id": "1744208945638",  
//   "version": "1.0",  
//   "params": {  
//     "manual_or": {  
//       "value": {  
//         "m_or_a": true  
//       }  
//     }  
//   }  
// }  

/**
 * @description: 发送手动事件
 * @param {bool} m_or_a - 手动或自动事件的标志，true表示手动事件
 * @return {*}
 */
void mqtt_send_manual_event(bool m_or_a){
    // 创建json数据
    cJSON *root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "id", "1744208945638");
    cJSON_AddStringToObject(root, "version", "1.0");    
    
    cJSON *params = cJSON_CreateObject();
    
    cJSON *manual_or = cJSON_CreateObject();
    
    // 创建value对象并将m_or_a添加到value对象中
    cJSON *value = cJSON_CreateObject();
    cJSON_AddBoolToObject(value, "m_or_a", m_or_a);
    
    cJSON_AddItemToObject(manual_or, "value", value);
    cJSON_AddItemToObject(params, "manual_or", manual_or);
    
    cJSON_AddItemToObject(root, "params", params);
    
    // 转化json数据为字符串
    char *my_test_data = cJSON_Print(root);
    // ESP_LOGI(TAG, "my_test_data=%s", my_test_data);

    // 发送事件的主题 $sys/3CqoyHWbCK/device/thing/event/post

    int ret = esp_mqtt_client_publish(client, MQTT_EVENT_TOPIC, my_test_data, strlen(my_test_data), 1, 0);
    if(ret != -1){
        // ESP_LOGI(TAG, "publish topic %s, msg_id=%d", MQTT_EVENT_TOPIC, ret);
    }
    // 释放内存
    free(my_test_data);
    // 释放json对象
    cJSON_Delete(root);
}
